package com.xw.unification.config;

import com.xw.unification.condition.UnificationCondition;
import com.xw.unification.condition.UnifiedRepeatableRequestCondition;
import com.xw.unification.config.WebUnificationMvcProperties.SignatureCheckProperties;
import com.xw.unification.entity.request.RepeatableRequestRewriteInterceptor;
import com.xw.unification.interceptor.RepeatableRequestFilter;
import com.xw.unification.interceptor.RequestSignatureCheckInterceptor;
import com.xw.unification.interceptor.UnifiedRequestInterceptorChain;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.nio.charset.Charset;
import java.util.List;


/**
 * 统一组件自动配置类
 *
 * @author qiwei
 * @date 2023-8-9 21:00:00
 * @since v1.0.0
 */
@Configuration
@Order(Ordered.HIGHEST_PRECEDENCE)
@Conditional(UnificationCondition.class)
@EnableConfigurationProperties({WebUnificationMvcProperties.class})
public class WebUnificationMvcBaseConfig implements WebMvcConfigurer, ApplicationContextAware {

    private static final Logger LOGGER = LoggerFactory.getLogger(WebUnificationMvcBaseConfig.class);

    private static int INTERCEPTOR_CHAIN_ORDER = 0;

    private ApplicationContext ctx;

    private final WebUnificationMvcProperties properties;

    private final UnifiedRequestInterceptorChain interceptorChain;

    public void setApplicationContext(ApplicationContext ctx) {
        this.ctx = ctx;
        if (interceptorChain != null) {
            interceptorChain.setApplicationContext(ctx);
        }
    }

    @Autowired
    public WebUnificationMvcBaseConfig(WebUnificationMvcProperties webUnificationMvcProperties) {
        properties = webUnificationMvcProperties;
        interceptorChain = new UnifiedRequestInterceptorChain(properties);
        initInterceptorChain(interceptorChain);
        LOGGER.info("[CustomerWebMvcConfig] ### CustomerWebMvcConfig auto configuration, enable");
    }

    @Bean
    @Conditional(UnifiedRepeatableRequestCondition.class)
    public RepeatableRequestFilter repeatableRequestFilter() {
        LOGGER.info("[CustomerWebMvcConfig] ### RepeatableRequestFilter bean auto inject");
        return new RepeatableRequestFilter(properties.getRequestBodyRepeatableRead());
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        addRepeatableRequestRewriteInterceptor(registry);
        if (interceptorChain.getInterceptorCounts() > 0) {
            LOGGER.info("[CustomerWebMvcConfig] ### RepeatableRequestFilter bean auto inject");
            registry.addInterceptor(interceptorChain).order(INTERCEPTOR_CHAIN_ORDER);
        }
    }

    private void initInterceptorChain(UnifiedRequestInterceptorChain interceptorChain) {
        if (interceptorChain == null || properties == null) {
            return;
        }
        // api signature configuration
        if (properties.getApiSignatureCheck() != null && properties.getApiSignatureCheck().isEnable()) {
            SignatureCheckProperties signatureCheck = properties.getApiSignatureCheck();
            String charsetName = signatureCheck.getCharsetName();
            try {
                Charset.forName(charsetName);
            } catch (Exception e) {
                throw new IllegalArgumentException("Charset name can not be parsed, charset name: " + charsetName);
            }
            LOGGER.info("[CustomerWebMvcConfig] ### RequestSignatureCheckInterceptor bean auto inject");
            interceptorChain.registerInterceptor(new RequestSignatureCheckInterceptor(properties));
        }
    }

    /**
     * 如果需要重写请求体, 则加入该拦截器
     *
     * @param registry  拦截器注册表
     */
    private void addRepeatableRequestRewriteInterceptor(InterceptorRegistry registry) {
        // repeatable request rewrite configuration
        WebUnificationMvcProperties.RepeatableRequestProperties repeatableProperties
                = properties.getRequestBodyRepeatableRead();
        WebUnificationMvcProperties.RewriteInterceptorProperties rewriteProperties
                = repeatableProperties.getRewriteInterceptor();
        if (repeatableProperties.isEnable() && rewriteProperties.isEnable()) {
            InterceptorRegistration registration = registry.addInterceptor(new RepeatableRequestRewriteInterceptor());
            List<String> interceptPaths = rewriteProperties.getInterceptPaths();
            if (interceptPaths != null && !interceptPaths.isEmpty()){
                registration.addPathPatterns(interceptPaths);
            }
        }
    }

}
